package face.pay.util;

import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.security.cert.X509Certificate;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: zkj
 * @Date: 2019/8/30 15:42
 * @Description:
 */
public class RSAEncryp {


        private static final String CIPHER_PROVIDER = "SunJCE";
        private static final String TRANSFORMATION_PKCS1Paddiing = "RSA/ECB/PKCS1Padding";

        private static final String CHAR_ENCODING = "UTF-8";//固定值，无须修改


        //数据加密方法
        private static byte[] encryptPkcs1padding(PublicKey publicKey, byte[] data) throws Exception {
            Cipher ci = Cipher.getInstance(TRANSFORMATION_PKCS1Paddiing, CIPHER_PROVIDER);
            ci.init(Cipher.ENCRYPT_MODE, publicKey);
            return ci.doFinal(data);
        }

        //加密后的秘文，使用base64编码方法
        private static String encodeBase64(byte[] bytes) throws Exception {
            return Base64.getEncoder().encodeToString(bytes);
        }

        /**
         * 对敏感内容（入参Content）加密
         * path 为平台序列号接口解密后的密钥 pem 路径
         */
        public static String rsaEncrypt(String Content, String path) throws Exception {
            final byte[] PublicKeyBytes = Files.readAllBytes(Paths.get(path));
            X509Certificate certificate = X509Certificate.getInstance(PublicKeyBytes);
            PublicKey publicKey = certificate.getPublicKey();

            return encodeBase64(encryptPkcs1padding(publicKey, Content.getBytes(CHAR_ENCODING)));
        }

        /**
         * 为了自己方便，多加个个传内容的，因为我解密后并没有保存到文件里，而是自己重新解密
         * 要问为什么？
         * 需求有多个服务商号，没办法
         *
         * @param Content
         * @param certStr
         * @return
         * @throws Exception
         */
        public static String rsaEncryptByCert(String Content, String certStr) throws Exception {
            X509Certificate certificate = X509Certificate.getInstance(certStr.getBytes());
            PublicKey publicKey = certificate.getPublicKey();
            return encodeBase64(encryptPkcs1padding(publicKey, Content.getBytes(CHAR_ENCODING)));
        }


      public static String decryptCertSN(String associatedData, String nonce, String cipherText, String apiv3Key) throws Exception{
        final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(apiv3Key.getBytes(), "AES");
        GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        cipher.updateAAD(associatedData.getBytes());
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
      }


    public static void rsaEncryptByCert(Map<String,String> map,List keylist, String certStr)  {

            if(map!=null && !map.isEmpty()){

                try{
                    Set<String> keySet  = map.keySet();

                    for(String key : keySet){

                        if(keylist.contains(key)){
                            String value = map.get(key);

                            if(StringUtils.isNotBlank(value)){
                                String cer_vaule = rsaEncryptByCert(value,certStr);
                                map.put(key,cer_vaule);
                            }
                        }

                    }

                }catch (Exception e){
                    e.printStackTrace();
                }

            }


    }


}
